﻿/** 把所有调用库改成class版本以后的测试脚本,龙与地下城2脚本(utf-8 with BOM)
  关键是使用了类MyUI,用该类设定了界面和热键绑定,同时实现了该类的接口
  
  By setycyas @2023-02-01
*/

/* 全局
*/{

  ;** 全局设置
  #NoEnv
  #Warn
  #MaxThreadsPerHotkey 1
  SendMode Input
  SetWorkingDir %A_ScriptDir%
  
  ;** 库调用
  #Include ..\MyAhkClass\MyKey.class.ahk ;按键相关库
  #Include ..\MyAhkClass\MyFuns.class.ahk ;自制常用函数库
  #Include ..\MyAhkClass\MyFaceDetector.class.ahk ;方向检测,需要新建实例
  #Include ..\MyAhkClass\MyNebula.class.ahk ;导入自定义的Nebula通用快捷键,需要新建实例使用
  #Include ..\MyAhkClass\MyXZone.class.ahk ;导入自定义的游聚通用快捷键,需要新建实例使用
  #Include ..\MyAhkClass\MyUI.class.ahk ;自定义界面设定和热键宏定义模块,需要新建实例使用
  
  ;** 全局常量
  ;用于调用MyFaceDetector类,但需要指定exe时才新建对象,这里先定义,实际上也是个常量,只是后面才赋值
  global FACE_DETECTOR
  ;实现MyUI类的接口
  global INTERFACE := {customGui: "customGui", onSubmit: "onSubmit"}
  ;可能选择的exe字符串表,用于gui组件,按组件格式写
  global EXE_LIST := MyFuns.join([MyNebula.EXE, MyXZone.EXE], "|")
  ;游戏按键
  global KEY1 := "x", KEY2 := "e"
  ;热键表
  global MACRO_KEYS := ["w", "q", "2", "3", "r", "a", "f"]
  ;技能名称字符串表,用于gui组件,按组件格式写
  global MACRO_LIST := "连发|下前A|下上A|牧师三连|下B|下前B|前A|A后防御|"
  MACRO_LIST := MACRO_LIST . "战士解剑|矮人解剑|小跳BB|小跳版边解剑|快速旋转A|盗贼空中滑行"
  ;预设
  global PRESET := {}
  PRESET["有盾"] := ["连发", "下前A", "下上A", "A后防御", "下前B", "小跳BB", "快速旋转A"]
  PRESET["牧师"] := ["连发", "下前A", "牧师三连", "A后防御", "下前B", "小跳BB", "快速旋转A"]
  PRESET["无盾"] := ["连发", "下前A", "下上A", "小跳BB", "下前B", "小跳BB", "快速旋转A"]
  PRESET["盗贼"] := ["连发", "下前A", "下上A", "小跳BB", "下前B", "盗贼空中滑行", "快速旋转A"]
  ;连发按键时按住键的时长
  global AUTOFIRE_DURATION := 25
  ;最大连发频率
  global MAX_FPS := 30
  
  ;** 绑定gui组件的全局变量,以G开头
  ;连发频率参数,设置上限为MAX_FPS,这里设定为6,矮人正好不会打出连击
  global GautoFireFPS := 10
  ;测试参数
  global GtestParam1 := 20, GtestParam2 := 500, GtestParam3 := 500 ;
  
  ;** 全局变量
  global fps := MyFuns.arrMin([GautoFireFPS, MAX_FPS]) ;实际设定连发的频率,上限为MAX_FPS
  global autoFireDelay := floor(1000/fps)-AUTOFIRE_DURATION ;连发延时
}

/* 操作与技能函数 
*/{
  
  ;** 技能函数,使用中文
  ;若GautoFireFPS为0,则做成单发
  连发(){
    local thisHotkey :=  MyFuns.getHotkey(A_ThisHotkey) ;触发技能的热键
    if (GautoFireFPS == 0){
      MyKey.keyDown(KEY1)
      while (GetKeyState(thisHotkey)){
        sleep, 10
      }
      MyKey.keyUp(KEY1)
    } else {
      MyKey.autoFire(thisHotkey, KEY1, AUTOFIRE_DURATION, autoFireDelay)
    }
  }
  下前A(){
    local face := FACE_DETECTOR.getFace()
	MyKey.inputSkill(["down", face, KEY1], [30, 30, 30])
  }
  下上A(){ ;通用,要用战士的2段升龙,可出招后按住攻击连发,或直接按住同样的技能键都行,因为ahk的一些模式下按住技能键也是技能连发,包含攻击键
    MyKey.press("down", 25)
	sleep, 25
    MyKey.pressKeys(["up", KEY1], [25], 25)
  }
  牧师三连(){ ;前a下前a-下上a,按住键才会持续出招,距离太近反而连不上
    local thisHotkey := MyFuns.getHotkey(A_ThisHotkey) ;触发技能的热键
    前A()
    sleep, 100
    下前A()
    sleep, 100
    if (!GetKeyState(thisHotkey)) {
      return
    }
    下上A()
  }
  下B(){
    MyKey.pressKeys(["down", KEY2], [25], 25)
  }
  下前B(){
    local face := FACE_DETECTOR.getFace()
	MyKey.inputSkill(["down", face, KEY2], [30, 30, 30])
  }
  前A(){
    local face := FACE_DETECTOR.getFace()
	MyKey.pressKeys([face, KEY1], [25], 25)
  }
  A后防御(){
    local thisHotkey := MyFuns.getHotkey(A_ThisHotkey) ;触发技能的热键
    local backFace := FACE_DETECTOR.getBackFace()
    MyKey.keyDown(KEY1)
    sleep, 50
    MyKey.press(backFace, 200)
    while (GetKeyState(thisHotkey)) {
      sleep, 20
    }
    MyKey.keyUp(KEY1)
  }
  战士解剑(){ ;参数测试效果还OK
    MyKey.press(KEY2, 50)
    sleep, 820
    MyKey.press(KEY1, 50)
    sleep, 200
  }
  矮人解剑(){ ;参数测试效果还OK
    MyKey.press(KEY2, 50)
    sleep, 705
    MyKey.press(KEY1, 50)
    sleep, 200
  }
  小跳BB(){
    MyKey.press(KEY2, 30)
    sleep, 50
    MyKey.press(KEY2, 30)
    sleep, 100
  }
  小跳版边解剑(){ ;战士精灵适用,测试后觉得参数500还行
    MyKey.press(KEY2, 30)
    sleep, 50
    MyKey.press(KEY2, 30)
    sleep, 500
    MyKey.press(KEY1, 30)
    sleep, 100
  }
  快速旋转A(){
    local thisHotkey := MyFuns.getHotkey(A_ThisHotkey) ;触发技能的热键
    while (GetKeyState(thisHotkey)) {
      MyKey.press("up", 20)
      sleep, 20
      MyKey.press("right", 20)
      sleep, 20
      MyKey.press("down", 20)
      sleep, 20
      MyKey.pressKeys(["left", KEY1], [20], 20)
      sleep, 20
    }
  }
  盗贼空中滑行(){ ;空中使用
    local backFace := FACE_DETECTOR.getBackFace()
    MyKey.pressKeys(["down", KEY1], [20], 20)
    sleep, 20
    MyKey.pressKeys([backFace, KEY2, KEY1], [20, 20], 20)
  }
  
  ;** 其他需要使用的函数
}

/* MyUI类相关接口实现
*/{
  ;自定义参数部分
  customGui(){
    Gui, Add, Text, x+20 y+20, 连发频率(FPS)： ;次/秒
    Gui, Add, Edit, xp+80 yp-3 W60 vGautoFireFPS, %GautoFireFPS%
    Gui, Add, Text, xp-80 yp+30, 测试参数1： ;
    Gui, Add, Edit, xp+80 yp-3 W60 vGtestParam1, %GtestParam1%
    Gui, Add, Text, xp-80 yp+30, 测试参数2： ;
    Gui, Add, Edit, xp+80 yp-3 W60 vGtestParam2, %GtestParam2%
    Gui, Add, Text, xp-80 yp+30, 测试参数3： ;
    Gui, Add, Edit, xp+80 yp-3 W60 vGtestParam3, %GtestParam3%
  }
  
  ;提交数据时的一些额外操作
  onSubmit(obj){
    local winTitle := "ahk_exe " . MyFuns.getVarValue(obj._exeComboBoxVar)
    ;初次提交时安装方向检测,对应的模拟器模块设定,游聚的时候设定一个切换热键生效
    if (obj._submitTimes == 1){
      FACE_DETECTOR := new MyFaceDetector(winTitle)
      if (winTitle == "ahk_exe " . MyNebula.EXE) {
        new MyNebula()
      }
      if (winTitle == "ahk_exe " . MyXZone.EXE) { ;游聚的热键生效切换
        new MyXZone("numpad2", "p")
      }
    }
    ;处理连发参数
    if (GautoFireFPS != 0){
      fps := MyFuns.arrMin([GautoFireFPS, MAX_FPS]) ;实际设定连发的频率,上限为MAX_FPS
      autoFireDelay := floor(1000/fps)-AUTOFIRE_DURATION ;连发延时
    }
  }
  
  ;关闭窗口时关闭脚本
  GuiClose(){
    ExitApp
  }
}

/* 运行脚本,启用UI
*/
(new MyUI("龙与地下城2(class版)", EXE_LIST, MACRO_LIST, MACRO_KEYS, PRESET, INTERFACE)).MenuReadPreset("有盾")
